#include "mainwindow.h"
#include "flashitem.h"
#include "staritem.h"
#include <QGraphicsItemAnimation>
#include <QTimeLine>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    createActions();                        //创建主窗体的所有动作
    createMenus();                          //创建主窗体的菜单栏

    scene = new QGraphicsScene;
    scene->setSceneRect(-200, -200, 400, 400);

    initScene();                            //初始化场景

    QGraphicsView *view = new QGraphicsView;
    view->setScene(scene);
    view->setMinimumSize(400, 400);
    view->show();

    setCentralWidget(view);
    resize(550, 450);
    setWindowTitle(tr("Graphics Items"));
}

MainWindow::~MainWindow()
{

}

void MainWindow::createActions()        //创建主窗体的所有动作
{
    newAct = new QAction(tr("新建"), this);
    clearAct = new QAction(tr("清除"), this);
    exitAct = new QAction(tr("退出"), this);
    addEllipseItemAct = new QAction(tr("加入 椭圆"), this);
    addPolygonItemAct = new QAction(tr("加入 多边形"), this);
    addTextItemAct = new QAction(tr("加入 文字"), this);
    addRectItemAct = new QAction(tr("加入 长方形"), this);
    addAlphaItemAct = new QAction(tr("加入 透明图片"), this);
    addFlashItemAct = new QAction(tr("加入 闪烁圆"), this);
    addAnimItemAct = new QAction(tr("加入 星星"), this);

    connect(newAct, SIGNAL(triggered()), this, SLOT(slotNew()));
    connect(clearAct, SIGNAL(triggered()), this, SLOT(slotClear()));
    connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
    connect(addEllipseItemAct, SIGNAL(triggered()), this, SLOT (slotAddEllipseItem()));
    connect(addPolygonItemAct, SIGNAL(triggered()), this, SLOT (slotAddPolygonItem()));
    connect(addTextItemAct, SIGNAL(triggered()), this, SLOT (slotAddTextItem()));
    connect(addRectItemAct, SIGNAL(triggered()), this, SLOT (slotAddRectItem()));
    connect(addAlphaItemAct, SIGNAL(triggered()), this, SLOT (slotAddAlphaItem()));
    connect(addFlashItemAct, SIGNAL(triggered()), this, SLOT(slotAddFlashItem()));
    connect(addAnimItemAct, SIGNAL(triggered()), this, SLOT(slotAddAnimationItem()));
}

void MainWindow::createMenus()          //创建主窗体的菜单栏
{
    QMenu *fileMenu = menuBar()->addMenu(tr("文件"));
    fileMenu->addAction(newAct);
    fileMenu->addAction(clearAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    QMenu *itemsMenu = menuBar()->addMenu(tr("元素"));
    itemsMenu->addAction(addEllipseItemAct);
    itemsMenu->addAction(addPolygonItemAct);
    itemsMenu->addAction(addTextItemAct);
    itemsMenu->addAction(addRectItemAct);
    itemsMenu->addAction(addAlphaItemAct);
    itemsMenu->addAction(addFlashItemAct);
    itemsMenu->addAction(addAnimItemAct);
}

void MainWindow::initScene()            //初始化场景
{
    int i;
    for (i = 0; i < 3; i++)
        slotAddEllipseItem();
    for (i = 0; i < 3; i++)
        slotAddPolygonItem();
    for (i = 0; i < 3; i++)
        slotAddTextItem();
    for (i = 0; i < 3; i++)
        slotAddRectItem();
    for (i = 0; i < 3; i++)
        slotAddAlphaItem();
    for (i = 0; i < 3; i++)
        slotAddFlashItem();
    for (i = 0; i < 3; i++)
        slotAddAnimationItem();
}

void MainWindow::slotNew()              //新建一个显示窗体
{
//    slotClear();
//    initScene();

    MainWindow *newWin = new MainWindow;
    newWin->show();
}

void MainWindow::slotClear()            //清除场景中所有的图元
{
    QList<QGraphicsItem *> listItem = scene->items();

    while (!listItem.empty())
    {
        scene->removeItem(listItem.at(0));
        listItem.removeAt(0);
    }
}

void MainWindow::slotAddEllipseItem()   //在场景中加入一个椭圆形图元
{
    QGraphicsEllipseItem *item = new QGraphicsEllipseItem(QRectF(0, 0, 80, 60));
    item->setPen(Qt::NoPen);
    item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddPolygonItem()   //在场景中加入一个多边形图元
{
    QVector<QPoint> v;
    v << QPoint(30, -15) << QPoint(0, -30) << QPoint(-30, -15) << QPoint(-30, 15) << QPoint(0, 30) << QPoint(30, 15);
    QGraphicsPolygonItem *item = new QGraphicsPolygonItem(QPolygonF(v));
    item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddTextItem()      //在场景中加入一个文字图元
{
    QFont font("Times", 16);
    QGraphicsTextItem *item = new QGraphicsTextItem("Hello Qt");
    item->setFont(font);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setDefaultTextColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddRectItem()      //在场景中加入一个长方形图元
{
    QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 60, 60));
    QPen pen;
    pen.setWidth(3);
    pen.setColor(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    item->setPen(pen);
    item->setBrush(QColor(qrand() % 256, qrand() % 256, qrand() % 256));
    item->setFlag(QGraphicsItem::ItemIsMovable);

    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddAlphaItem()     //在场景中加入一个透明蝴蝶图片
{
    QGraphicsPixmapItem *item = scene->addPixmap(QPixmap(":/images/image.png"));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddFlashItem()     //在场景中加入一个闪烁图元
{
    FlashItem *item = new FlashItem;
    scene->addItem(item);
    item->setPos((qrand() % int(scene->sceneRect().width())) - 200, (qrand() % int(scene->sceneRect().height())) - 200);
}

void MainWindow::slotAddAnimationItem() //在场景中加入一个动画星星
{
    // 图元的动画有两种方式实现：
    // 1. 在图元类中利用定时器和重绘函数paint实现
    // 2. 利用QGraphicsItemAnimation和QTimeLine实现

//    1.创建 QTimeLine对象的时候传入时间值，单位是毫秒，该时间就是动画运行的时间；
//    2.设置帧率范围，通过setFrameRange()进行设置，该值表示在规定的时间内将要执行多少帧；
//    3.连接frameChanged(）信号，并在槽中对需要实现动画的控件进行赋值，如QProgressBar的setValue().
//    4.调用 start(）开始执行时间轴动作。
//    当 QTimeLine调用 start()后将进入运行状态，并会发出frameChanged()信号，而连接该信号的槽中将会不断的对目标控件进行相应的动作赋值，从而实现动画效果。可以通过调用setUpdateInterval()来指定更新间隔。
//    完成后，QTimeLine进入NotRunning状态，并发出finished().
//QTimeLine _timeLine;
//_timeLine.setDuration(3000);    //持续时间
//_timeLine.setLoopCount(0);        //无限循环
//_timeLine.setFrameRange(0, 100);//frameChanged()发出的值在0-100之间
//_timeLine.setCurveShape(QTimeLine::SineCurve);    //frameChanged()发出的值像sin曲线一样，1,2,...,99,100,99,...,2,1
//_timeLine.setUpdateInterval(25);    //更新频率（也就是frameChanged(int)的执行速度），每25ms更新一次，相当于每秒40帧，
//connect(&_timeLine, SIGNAL(frameChanged(int)), this, SLOT(scaleAnimation(int)));
//_timeLine.start();

    // 曲线形状：
//    QTimeLine 的核心在于 valueForTime() 函数，该函数在给定时间内生成 0 和 1 之间的值。
//    此值通常用于描述动画的步骤，其中 0 是动画的第一步，1 是最后一步。
//    运行时，QTimeLine 通过调用 valueForTime() 生成 0 和 1 之间的值并发出 valueChanged() 信号。
//    默认情况下，valueForTime() 应用插值算法生成这些值，可以通过调用 setCurveShape() 从一组预定义的时间轴算法中进行选择。
//    对于自定义时间轴，可以重新实现 valueForTime()，在这种情况下，QTimeLine 的 curveShape 属性被忽略。

    StarItem *item = new StarItem;
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;
    anim->setItem(item);

    QTimeLine *timeLine = new QTimeLine(4000);
    timeLine->setCurveShape(QTimeLine::SineCurve); // 值正弦式增长
    timeLine->setLoopCount(0); // =0表示无限循环

    anim->setTimeLine(timeLine);

    int y = (qrand() % 400) - 200;
    for (int i = 0; i < 400; i++)
    {
        // QGraphicsItemAnimation自带了setPosAt()、setRotationAt()、setScaleAt()等方法可以用来移动、旋转、放缩QGraphicsItem，
        // 但其默认的OriginPoint是这个Item的左上角，
        anim->setPosAt(i / 400.0, QPointF(i - 200, y)); // Sets the position of the item at the given step value to the point specified.
    }
    timeLine->start();
    scene->addItem(item);
}
